#pragma once

#include <iostream>
#include <vector>
#include <string>
#include <cstring>
#include <unordered_set>

#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include "Log.hpp"

namespace Router
{
    class InetAddr
    {
    public:
        std::string _ip;
        in_addr _sin_addr;
        uint16_t _netport;
        uint16_t _hostport;
        

        InetAddr(std::string ip, uint16_t port)
            :_ip(ip),
            _hostport(port)
        {
            _netport = htons(_hostport);

            inet_pton(AF_INET, _ip.c_str(), &_sin_addr);
        }

        // i1 == i2
        bool operator==(InetAddr i2)
        {
            return _ip == i2._ip && _hostport == i2._hostport;
        }

    };

    class Router
    {
    public:
        void Init(int sockfd)
        {
            _sockfd = sockfd;
        }

        bool adduser(InetAddr newuser)
        {
            for(auto e : _online_user)
            {
                if(e == newuser)
                    return false;
            }
            _online_user.emplace_back(newuser);
            LOG(DEBUG, "server add a user: [ip: %s port: %d], UserNum: %d\n", newuser._ip.c_str(), newuser._hostport, _online_user.size());
            
            return true;
        }

        void Boardcast(std::string message)
        {
            for(auto e : _online_user)
            {
                sockaddr_in client;
                memset(&client, 0, sizeof(client));
                socklen_t len = sizeof(client);

                client.sin_family = AF_INET;
                client.sin_port = e._netport;
                client.sin_addr = e._sin_addr;

                std::string formatmsg = "[" + e._ip + ": " + std::to_string(e._hostport)+"] #" + message + '\n'; 

                sendto(_sockfd, formatmsg.c_str(), formatmsg.size(), 0, (sockaddr*)&client, len);
            }
        }
    private:
        std::vector<InetAddr> _online_user;
        int _sockfd;
    };
}